import socket
from header import *
from rdt_function import *
from multiprocessing import Process,Queue

receive_win_size_in_lget = 50
m_in_lget = 0
currentAck_in_lget_s = 0
currentSend_in_lget = 0
current_cache_in_lget = []
buffer_in_lget = ''
totalAck = 0
q = Queue()
serverport = 9000

def lget_re(sock,f,):
    global receive_win_size_in_lget
    global m_in_lget
    global currentAck_in_lget_s
    global currentSend_in_lget
    global current_cache_in_lget
    global buffer_in_lget
    global totalAck
    global q

    while 1:
        print("ggggggggggggggggggggggggggg")
        data,addr = sock.recvfrom(1024)
        pk = Packet()
        pk.decode(data)
        receive_win_size_in_lget = pk.receiveWindowSize

        if pk.seqNo != 0:
            q.put(pk.seqNo)
        else:
            currentAck_in_lget_s = pk.ackNo
            print("total ack "+str(totalAck))
            print("curr_ack"+str(currentAck_in_lget_s))
            for p in current_cache_in_lget:
                if p.ackNo == currentAck_in_lget_s:
                    current_cache_in_lget.remove(p)
        if currentAck_in_lget_s == totalAck:
            m_in_lget = 1
        else:
            m_in_lget = 0
        if currentAck_in_lget_s == totalAck:
            break

<<<<<<< HEAD
def lget(port, address, f, filesize):
    sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    sock.bind(('127.0.0.1',port))
    global receive_win_size_in_lget
    global m_in_lget
    global currentAck_in_lget_s
    global currentSend_in_lget
    global current_cache_in_lget
    global buffer_in_lget
    global totalAck
    global q

    thread1 = threading.Thread(target=lget_re, args=(sock,f,))#recv
    thread1.start()

    mode = filesize%200

    add = 0
    if mode != 0:
        add = 1
    totalAck = int(filesize/200) + add
=======
def lget(sock, address, f, filesize):
    if filesize % 200 == 0:
        totalAck = filesize / 200
    else:
        totalAck = int(filesize/200) + 1
    print("total ack", totalAck)
>>>>>>> ff1a31a8d97c44442ac683b2705ebbc705e8f5ba

    while 1:

        if receive_win_size_in_lget > 0:

            if not q.empty():
                currentAck_in_lget_s = q.get()
                for p in current_cache_in_lget:
                    if p.ackNo == currentAck:
                        buffer = p.data
                pk.make({'seqNo': 0, 'ackNo': currentAck_in_lget_s, 'receiveWindowSize': 50, 'ACK': 0, 'SYN': 0, 'FIN': m_in_lget, 'data': buffer})
                sock.sendto(pk.bitStream, address)
            else:
                if currentSend_in_lget != totalAck + 1:
                    buffer_in_lget = f.read(200)
                    pk = Packet()
                    print("send"+str(currentSend_in_lget+1))
                    currentSend_in_lget = currentSend_in_lget + 1
                    if currentSend_in_lget == totalAck:
                        m_in_lget = 1
                    pk.make({'seqNo': 0, 'ackNo': currentSend_in_lget, 'receiveWindowSize': receive_win_size_in_lget, 'ACK': 0, 'SYN': 0, 'FIN': m_in_lget, 'data': buffer_in_lget})
                    current_cache_in_lget.append(pk)
                    print("total "+str(totalAck))
                    print("cerrent_send "+str(currentSend_in_lget))
                    time.sleep(0.03)
                    sock.sendto(pk.bitStream, address)
                else:
                    print("in close")
                    f.close()
                    break


    """
    while 1:
        print(totalAck)

        buffer = f.read(200)
        print(buffer)
        pk = Packet()
        if currentAck+1 == totalAck:
            m = 1
        else:
            m = 0
        pk.make({'seqNo': 0, 'ackNo': currentAck+1, 'receiveWindowSize': 50, 'ACK': 0, 'SYN': 0, 'FIN': m, 'data': buffer})
        print(pk.bitStream)
        sock.sendto(pk.bitStream, address)
        data, addr = sock.recvfrom(1024)
        print(data)
        pk_re = Packet()
        pk_re.decode(data)
        currentAck = pk_re.ackNo
        print(currentAck)
        if currentAck == totalAck:
            print("in close")
            f.close()
            break
    """

def lsend(sock, addr, fp):
    print("ready to receive file from", addr)
    while 1:
        data, addr = sock.recvfrom(1024)
        print(data)
        pk_rcv = Packet()
        pk_rcv.decode(data)
        print(pk_rcv.ACK)
        print(pk_rcv.SYN)
        print(pk_rcv.FIN)
        print(pk_rcv.ackNo)
        if pk_rcv.FIN == 1:
            print("Receiving is over, file in close.")
            fp.close()
            break
        fp.write(pk_rcv.data)
        print("Reply for acknowledging receiving the data from", addr)
        pk_re = Packet()
        pk_re.make({'seqNo': 0, 'ackNo': pk_rcv.ackNo, 'receiveWindowSize': 0, 'ACK': 0, 'SYN': 0, 'FIN': 0})
        sock.sendto(pk_re.bitStream, addr)

serverAddress = '127.0.0.1'
port = 9999
bufferSize = 1024
target = (serverAddress, port)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(target)
split = "|:|"
pk_to_send = ""
serverWinsize = 50

while 1:
    currentAck = 0
    data = 0
    address = 0
    data, address = sock.recvfrom(1024)
    pk = Packet()
    pk.decode(data)
    ackNo = pk.ackNo
    pk_ack = Packet()
    print(ackNo)
    pk_ack.make({'seqNo': 0, 'ackNo': ackNo, 'receiveWindowSize': 50, 'ACK': 0, 'SYN':0, 'FIN': 0,'data':str(serverport).encode('utf-8')})

    sock.sendto(pk_ack.bitStream, address)
    # send add
    target = (address, port)
    rdt_send_for_server(address, pk_ack.bitStream, sock, pk.ackNo)
    #sock.sendto(pk_ack.bitStream,address)

    method_and_filename = pk.data.decode('utf-8')
    method_and_filename = method_and_filename.split(split)
    method = method_and_filename[0]
    filename = method_and_filename[1]
    clientport = int(method_and_filename[2])
    print(method)
    print(filename)

    if method == 'lsend':
        try:
            fp = open("server/"+filename, 'wb')
        except:
            print("open file error")
        thread_lsend = threading.Thread(target=lsend, args=(sock, address, fp))
        thread_lsend.start()
        thread_lsend.join()
    elif method == 'lget':
        print("into lget")
        try:
            f = open("server/"+filename, 'rb')
            filesize = os.path.getsize("server/"+filename)
        except:
            print("open file error")

        print(filesize)

        thread_lget = threading.Thread(target=lget, args=(serverport, (address[0], clientport), f, filesize))#send
        thread_lget.start()
        thread_lget.join()

    else:
        pass



"""
if method == "lsend":
  f = open("server/"+filename, 'wb')
  print("open success")
  while 1:
    #receive filename
    content, addr = sock.recvfrom(1024)
    print(content)
    pk = Packet()
    pk.decode(content)
    f.write(pk.data)
    #print(pk.data)
    if len(pk.data) < 100:
      break;
elif method == "lget":
  f = open("data/"+filename, 'rb')
  msg = f.read()
  f.close();
  l = 0
  while l < len(msg):
    if l+1024 > len(msg):
      fragment = msg[l:len(msg)]
      sock.sendto(fragment, address)
      break
    fragment = msg[l:l+1024]
    l = l + 1024
    sock.sendto(fragment, address)

  print("Waiting...")
  #connectThread = threading.Thread(target=handleConnection, args=(address,filename))
  #connectThread.start()
else:
  print("error")


# a packet used in download

"""

"""
def send_udp():
  pass

def recve_udp():
  pass

def main():
  while 1:
    receive_pk, addr_from = sock.recvfrom(1024)
    if addr_from in address_current_handle:
      find_index = address_current_handle[addr_from]
      t = threads[find_index]
    else:
      t = threading.Thread(target = send_udp(), args={})
      threads.append(t)
      count = len(threads)
      address_current_handle[addr_from] = count -1

if __name__ == '__main__':
  main()
"""
"""
def handleConnection(address, filename):
  pk = Packet()
  threadSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  try:
    f = open("data/"+ filename, 'rb')
    msg = f.read()
    msg = str(msg, encoding='utf-8')
    f.close()
    print("open file success")
  except:
    msg = "FNF"
    pk.make(msg)
    pk_to_send = str(pk.length) + split + str(pk.seqNo) + split + pk.data
    threadSock.sendto(pk_to_send.encode('utf-8'), address)
    print("cannot find the file in server.")
  l = 0
  while 1:
    if l+1024 > len(msg):
      fragment = msg[l:len(msg)]
      pk.make(fragment)
      pk_to_send = str(pk.length) + split + str(pk.seqNo) + split + pk.data
      threadSock.sendto(pk_to_send.encode('utf-8'), address)
      break
    fragment = msg[l:l+1024]
    pk.make(fragment)
    pk_to_send = str(pk.length) + split + str(pk.seqNo) + split + pk.data
    threadSock.sendto(pk_to_send.encode('utf-8'), address)
    l = l+1024
"""
